#include <bits/stdc++.h>

using namespace std;

template<const int _n,const int _m>
struct Edge
{
	struct Edge_base { int	to,next; } e[_m]; int	cnt,p[_n];
	Edge() { clear(); } void	clear() { cnt=0,memset(p,0,sizeof(p)); }
	void	insert(const int x,const int y)
	{ e[++cnt].to=y; e[cnt].next=p[x]; p[x]=cnt; return ; }
	void	link(const int x,const int y) { insert(x,y); insert(y,x); }
	int	start(const int x) { return p[x]; }
	Edge_base&	operator[](const int x) { return e[x]; }
}; struct tri { int	lx,rx,mx; };

int	n,m,ind,a[110000];
int	Dfn[110000],Head[110000],Pre[110000],hv[110000];
int	lx[270000],rx[270000],mx[270000],f[270000];
Edge<110000,210000>e;

void	push_down(const int num,const int l,const int r)
{
	if(f[num]!=0x3f3f3f3f)
	{
		lx[num]=rx[num]=f[num];
		mx[num]=1;
		if(l!=r) f[num<<1]=f[num<<1|1]=f[num];
		f[num]=0x3f3f3f3f;
	}
	return ;
}

void	update(const int num,const int l,const int r)
{
	int	mid=l+((r-l)>>1);
	push_down(num<<1,l,mid);
	push_down(num<<1|1,mid+1,r);
	lx[num]=lx[num<<1];
	rx[num]=rx[num<<1|1];
	mx[num]=mx[num<<1]+mx[num<<1|1]-(rx[num<<1]==lx[num<<1|1]);
	return ;
}

int	Init_Dfs(const int S,const int fa)
{
	int	s=1,Max=0;
	for(int i=e.start(S); i; i=e[i].next)
	{
		if(e[i].to==fa)continue;
		int temp=Init_Dfs(e[i].to,S);
		if(temp>Max)Max=temp,hv[S]=e[i].to;
		s+=temp;
	}
	return s;
}

void	Dfs(const int S,const int fa)
{
	if(!Head[S])Head[S]=Head[fa];
	Dfn[S]=++ind;
	if(hv[S])Dfs(hv[S],S);
	for(int i=e.start(S); i; i=e[i].next)
	{
		if(e[i].to==hv[S] || e[i].to==fa)continue;
		Head[e[i].to]=e[i].to;
		Pre[e[i].to]=S;
		Dfs(e[i].to,S);
	}
	return ;
}

tri	Merge(const tri temp1,const tri temp2)
{
	if(temp1.lx==-1 && temp1.rx==-1 && temp1.mx==-1)return temp2;
	if(temp2.lx==-1 && temp2.rx==-1 && temp2.mx==-1)return temp1;
	return (tri)
	{
		temp1.lx,temp2.rx,temp1.mx+temp2.mx-(temp1.rx==temp2.lx)
	};
}

tri	REV(const tri temp)
{
	return (tri)
	{
		temp.rx,temp.lx,temp.mx
	};
}

void	Change(const int l,const int r,const int num,const int s,const int t,const int d)
{
	if(s<=l && r<=t)
	{
		f[num]=d;
		push_down(num,l,r);
		return ;
	}
	int	mid=l+((r-l)>>1);
	push_down(num,l,r);
	if(s<=mid)Change(l,mid,num<<1,s,t,d);
	if(t>mid)Change(mid+1,r,num<<1|1,s,t,d);
	update(num,l,r);
	return ;
}

tri	Query(const int l,const int r,const int num,const int s,const int t)
{
	if(s<=l && r<=t)
	{
		push_down(num,l,r);
		return (tri)
		{
			lx[num],rx[num],mx[num]
		};
	}
	int	mid=l+((r-l)>>1);
	push_down(num,l,r);
	if(t<=mid)return Query(l,mid,num<<1,s,t);
	if(s>mid)return Query(mid+1,r,num<<1|1,s,t);
	return Merge(Query(l,mid,num<<1,s,t),Query(mid+1,r,num<<1|1,s,t));
}

int	Count(int x,int y)
{
	tri	temp1=(tri) {-1,-1,-1},temp2=(tri)
	{
		-1,-1,-1
	};
	while(Head[x]!=Head[y])
	{
		if(Dfn[Head[x]]>Dfn[Head[y]])
		{
			temp1=Merge(Query(1,n,1,Dfn[Head[x]],Dfn[x]),temp1);
			x=Pre[Head[x]];
		}
		else
		{
			temp2=Merge(Query(1,n,1,Dfn[Head[y]],Dfn[y]),temp2);
			y=Pre[Head[y]];
		}
	}
	if(Dfn[x]>Dfn[y])return Merge(REV(temp1),Merge(REV(Query(1,n,1,Dfn[y],Dfn[x])),temp2)).mx;
	return Merge(REV(temp2),Merge(REV(Query(1,n,1,Dfn[x],Dfn[y])),temp1)).mx;
}
void	Color(int x,int y,const int z)
{
	while(Head[x]!=Head[y])
	{
		if(Dfn[Head[x]]>Dfn[Head[y]])
		{
			Change(1,n,1,Dfn[Head[x]],Dfn[x],z);
			x=Pre[Head[x]];
		}
		else
		{
			Change(1,n,1,Dfn[Head[y]],Dfn[y],z);
			y=Pre[Head[y]];
		}
	}
	Dfn[x]>Dfn[y]?Change(1,n,1,Dfn[y],Dfn[x],z):Change(1,n,1,Dfn[x],Dfn[y],z);
	return ;
}

int main()
{
	int	x,y,z,i;
	char op[10];

	scanf("%d%d",&n,&m);
	memset(f,0x3f3f3f3f,sizeof(f));
	for(i=1; i<=n; ++i) scanf("%d",&a[i]);
	for(i=1; i<n; ++i) scanf("%d%d",&x,&y),e.link(x,y);
	Init_Dfs(1,0);
	Head[1]=1;
	Dfs(1,1);
	for(i=1; i<=n; ++i) Change(1,n,1,Dfn[i],Dfn[i],a[i]);
	while(m--)
	{
		scanf("%s",op);
		if(op[0]=='C')
		{
			scanf("%d%d%d",&x,&y,&z);
			Color(x,y,z);
		}
		else
		{
			scanf("%d%d",&x,&y);
			printf("%d\n",Count(x,y));
		}
	}
	return 0;
}
